/**********************************************************************
 * $Id SkyConf.cpp   2011-08-01 
 * swhors@naver.com
 *
 **********************************************************************/

/**********************************************************************
 * 2011-08-23 15:52 : Strength that check useless space.
 **********************************************************************/

#include "config.h"

#include <iostream>
#include <stdio.h>
#include <memory.h>
#include <stdlib.h>

#include "skylistener.h"
#include "constant.h"
#include "ast_peg.h"

#include "SkyConf.h"

using namespace peg_templ;
using namespace std;

CSkyConf::CSkyConf()
{
   InitConf();
   memset(mConfFileName, 0, sizeof(char) * MAX_PATH_LENGTH );
}
CSkyConf::~CSkyConf()
{
}

/* 
 * @desc  init configuration value.
 *
 * @return -void-
 */
void CSkyConf::InitConf()
{
   mMaxCall  = 0;
   mWaitTime = 0;
   
   memset( mCallListPath,  0, MAX_PATH_LENGTH);
   memset( mCallOutPath,   0, MAX_PATH_LENGTH);
   memset( mRecordingPath, 0, MAX_PATH_LENGTH);
   memset( mAstUserName,   0, USERNAME_MAX_LEN);
   memset( mOutChanName,   0, USERNAME_MAX_LEN);
   memcpy( mOutChanName,
           DEFAULT_CHANNAME,
           strlen( DEFAULT_CHANNAME ) );
}

/* 
 * @desc  Print configuration value.
 *
 * @return -void-
 */
void CSkyConf::PrintConf()
{
   cout << "LIST:"    << mCallListPath << endl;
   cout << "OUTCALL:" << mCallOutPath  << endl;
   cout << "MAXCALL:" << mMaxCall      << endl;
   cout << "RECORD:"  << mRecordingPath<< endl;
   cout << "WAITTIME:"<< mWaitTime     << endl;
   cout << "ASTUSER:" << mAstUserName  << endl;
   cout << "OUTCHANNAME:" << mOutChanName << endl;
}

/* 
 * @desc  check useless space at last ptr. and remove that point.
 *
 * @param  [in][out] aLineBufPtr
 * 
 * @return -void-
 */
void CSkyConf::removeEndSpace(char *aLineBufPtr )
{
   int sIntRemovePoint = 0;
   if ( aLineBufPtr != NULL )
   {
      sIntRemovePoint = strlen( aLineBufPtr ) - 1;
      removeSpace(aLineBufPtr, sIntRemovePoint );
   }
   else
   {
      /* do nothing */
   }
}

/* 
 * @desc  check useless space at first ptr. and remove that point.
 *
 * @param  [in][out] aLineBufPtr
 * 
 * @return -void-
 */
void CSkyConf::removeFirstSpace( char *aLineBufPtr )
{
   if ( aLineBufPtr != NULL )
   {
      removeSpace(aLineBufPtr, 0 );
   }
   else
   {
      /* do nothing */
   }
}

/* 
 * @desc  check useless space at point. and remove that point.
 *
 * @param  [in][out] aLineBufPtr
 * @param  [in]      aIntChkPoint - Check Point
 * 
 * @return -void-
 */
void CSkyConf::removeSpace( char *aLineBufPtr , int aIntChkPoint )
{
   int sIntTotalStrLen= 0;
   int sEndPoint = 0;

   if ( aLineBufPtr == NULL )
   {
      /* do nothing */
   }
   else
   {
      sIntTotalStrLen = strlen( aLineBufPtr );
   
      sEndPoint = sIntTotalStrLen - 1;
      
      if ( aIntChkPoint < sEndPoint )
      {
         if ( aLineBufPtr[ aIntChkPoint ] == ' ' )
         {
            int sMoveLen = sIntTotalStrLen - aIntChkPoint + 1;
            int sNextPtr = aIntChkPoint + 1;
            memmove( (void*) &aLineBufPtr[aIntChkPoint],
                     &aLineBufPtr[sNextPtr],
                     sMoveLen );
            aLineBufPtr[ sEndPoint ] = 0;
         }
         else
         {
            /* do nothing */
         }
      }
      else
      {
         if ( aLineBufPtr[ sEndPoint ] == ' ' )
         {
            aLineBufPtr[ sEndPoint - 1 ] = 0;
         }
      }
   }
}

/* 
 * @desc  parse line buf. and set configuration data.
 *
 * @param  [in] aStrLine 
 * 
 * @return Result code;
 */
int CSkyConf::ParseConf( char *aStrLine )
{
   PBYTE sTmp         = NULL;
   PBYTE sStart       = NULL;
   BYTE  sBuff[32]    = {0,};
   int   sLineLen     = 0;
   int   sCount       = 0;
   
   sTmp = (PBYTE)aStrLine;
   
   sLineLen = strlen( aStrLine );
   
   /* remove carriage return. */
   for( sCount = 0; sCount < sLineLen ; sCount++ )
   {
      if( sTmp[sCount] == '\r' ||
             sTmp[sCount] == '\n')
      {
         sTmp[sCount] = 0;
         sLineLen--;
      }
   }
   
   if ( maxcall_f::Matches( sTmp, sStart ) )
   {
      memset( sBuff, 0, 32);
      memcpy( sBuff, sTmp, (sLineLen - 8) );
      
      if ( sBuff[0] == 0 )
      {
         mMaxCall = atoi((char*)&sBuff[1]);
      }
      else
      {
         mMaxCall = atoi((char*)&sBuff);
      }
       
      return 1;
   }
   else
   {
      /* do nothing */
   }

   sTmp = (PBYTE)aStrLine;
   
   if ( waittime_f::Matches( sTmp, sStart ) )
   {
      memset( sBuff, 0, 32);
      memcpy( sBuff, sTmp, (sLineLen - 8) );
      
      if ( sBuff[0] == 0 )
      {
         mWaitTime = atoi((char*)&sBuff[1]);
      }
      else
      {
         mWaitTime = atoi((char*)&sBuff);
      }
       
      return 1;
   }
   else
   {
      /* do nothing */
   }
   
   sTmp = (PBYTE)aStrLine;
   
   if ( list_f::Matches( sTmp, sStart ) )
   {
      memset( mCallListPath, 0, MAX_PATH_LENGTH );
      memcpy( mCallListPath,
              sTmp,
              (sLineLen-5));
      
      removeFirstSpace( mCallListPath );
      removeEndSpace( mCallListPath );
      
      return 1;
   }
   else
   {
      /* do nothing */
   }
   
   sTmp = (PBYTE)aStrLine;
    
   if ( outcall_f::Matches( sTmp, sStart ) )
   {
      memset( mCallOutPath, 0, MAX_PATH_LENGTH );
      memcpy( mCallOutPath,
              sTmp,
              (sLineLen - 8 ) );
      
      removeFirstSpace( mCallOutPath );
      removeEndSpace( mCallOutPath );
      
      return 1;
   }
   else
   {
      /* do nothing */
   }
   
   sTmp = (PBYTE)aStrLine;
   
   if ( record_f::Matches( sTmp, sStart ) )
   {
      memset( mRecordingPath, 0, MAX_PATH_LENGTH );
      memcpy( mRecordingPath,
              sTmp,
              (sLineLen - 7 ) );
      
      removeFirstSpace( mRecordingPath );
      removeEndSpace( mRecordingPath );
      
      return 1;
   }
   else
   {
      /* do nothing */
   }
   
   if ( astuser_f::Matches( sTmp, sStart ) )
   {
      memset( mAstUserName, 0, USERNAME_MAX_LEN );
      memcpy( mAstUserName,
              sTmp,
              (sLineLen - 8 ) );
      
      removeFirstSpace( mAstUserName );
      removeEndSpace( mAstUserName );
      
      return 1;
   }
   else
   {
      /* do nothing */
   }
   
   if ( outchanname_f::Matches( sTmp, sStart ) )
   {
      memset( mOutChanName, 0, USERNAME_MAX_LEN );
      memcpy( mOutChanName,
              sTmp,
              (sLineLen - 8 ) );
      
      removeFirstSpace( mOutChanName );
      removeEndSpace( mOutChanName );
      
      return 1;
   }
   else
   {
      /* do nothing */
   }
   
   return 0;
}

/* 
 * @desc  Read Configuration File, and call parse function.
 *
 * @param  [in] aStrConfFileName
 * 
 * @return Result code;
 */
int CSkyConf::LoadConf( char *aStrConfFileName )
{
   FILE *fp       = NULL;
   char *sLinePtr = NULL;
   char sLineBuf[READ_LINE_BUF_LEN];
   
   fp = fopen( aStrConfFileName, "r+t");
   
   if (fp != NULL)
   {
      snprintf( mConfFileName,
                MAX_PATH_LENGTH,
                "%s",
                aStrConfFileName );
      
      memset( sLineBuf, 0, READ_LINE_BUF_LEN);
      
      sLinePtr = fgets( sLineBuf, READ_LINE_BUF_LEN, fp);
      while ( sLinePtr )
      {
#ifdef _DEBUG
         printf("[%s %d] %s\n", __FILE__, __LINE__, sLinePtr );
#endif
         if ( ( *sLinePtr != '#' ) && 
              ( *sLinePtr != '*' ) )
         {
            (void)ParseConf( sLinePtr );
             
            memset(sLineBuf, 0, READ_LINE_BUF_LEN);
         }
         
         sLinePtr = fgets( sLineBuf, READ_LINE_BUF_LEN, fp);
      }
      fclose(fp);
      return 1;
   }
   else
   {
      /* do nothing */
   }
   return 0;
}

/* 
 * @desc  Write configuration file by inner data.
 *
 * @param  [in] aStrConfFileName - out file name.
 * 
 * @return Result code;
 */
int CSkyConf::WriteConf( char *aStrConfFileName )
{
   snprintf( mConfFileName,
             MAX_PATH_LENGTH,
             "%s",
             (char*)aStrConfFileName );
   return WriteConf();
}

/* 
 * @desc  Write configuration file by inner data using default file name.
 *
 * @return Result code;
 */
int CSkyConf::WriteConf()
{
   FILE *fp = NULL;
   
   fp = fopen( mConfFileName, "w+t");
   
   if ( fp )
   {
      fprintf( fp, "### Sky Listener Configuration ###\n");
      fprintf( fp,
               "LIST:%s\n", 
               ( strlen(mCallListPath) > 0? mCallListPath:"" ) );
      fprintf( fp,
               "OUTCALL:%s\n", 
               ( strlen(mCallOutPath) > 0 ? mCallOutPath:"" ) );
      fprintf( fp,
               "MAXCALL:%d\n", 
               (mMaxCall > 0 ? mMaxCall: 1 ) );
      fprintf( fp,
               "RECORD:%s\n", 
               ( strlen(mRecordingPath) > 0 ? mRecordingPath:"" ) );
      fprintf( fp,
               "WAITTIME:%d\n", 
               ( mWaitTime > 0 ? mWaitTime: 2 ) );
      fprintf( fp,
               "ASTUSER:%s\n",
               ( strlen( mAstUserName ) > 0 ? mAstUserName:"" ) );
      fprintf( fp,
               "OUTCHANNAME:%s\n",
               ( strlen( mAstUserName ) > 0 ? mAstUserName:"" ) );
      fclose( fp );
      return 1;
   }
   return 0;
}

#ifdef _TEST_CONF

/* 
 * @desc Test module for this class .
 *
 * @param  [in] aArgc.
 * @param  [in] aArgv.
 * 
 * @return Result code;
 */
int main( int aArgc, char **aArgv)
{
   if ( aArgc == 2 )
   {
      CSkyConf conf;
      conf.InitConf();
      conf.LoadConf(aArgv[1]);
      conf.PrintConf();
      cout << "Out file : " << conf.mCallOutPath << "/1.call" << endl;
   }
   else
   {
      printf("Usage :                 \n"\
             "     %s [conf file name]\n",
             aArgv[0]);
   }
   return 1;
}
#endif // _TEST_CONF
